#include <stdio.h>
#include <string.h>
#include <disp_manager.h>

// disp_manager.c中一定是不涉及直接对Framebuffer操作的代码的
// disp_manager.c一定是对DispOpr进行操作


static struct DispOpr *g_DispDevs = NULL;
static struct DispOpr *g_DispDefault = NULL;
static DispBuff g_tDispBuff;
static int line_width;
static int pixel_width;


void DrawFontBitMap(PFontBitMap ptFontBitMap, unsigned int dwColor)
{
    int i, j, p, q;
	int x = ptFontBitMap->tRegion.iLeftUpX;
	int y = ptFontBitMap->tRegion.iLeftUpY;
    int x_max = x + ptFontBitMap->tRegion.iWidth;
    int y_max = y + ptFontBitMap->tRegion.iHeigh;
	int width = ptFontBitMap->tRegion.iWidth;
	unsigned char *buffer = ptFontBitMap->pPixelDatas;

    for ( j = y, q = 0; j < y_max; j++, q++ )
    {
        for ( i = x, p = 0; i < x_max; i++, p++ )
        {
            if ( i < 0      || j < 0       ||
                i >= g_tDispBuff.iXres || j >= g_tDispBuff.iYres )
            continue;
			
            if (buffer[q * width + p])
	            PutPixel(i, j, dwColor);
        }
    }
	
}


int PutPixel(int x, int y, unsigned int dwColor)
{
	unsigned char *pen_8 = (unsigned char *)(g_tDispBuff.buff+y*line_width+x*pixel_width);
	unsigned short *pen_16;	
	unsigned int *pen_32;	

	unsigned int red, green, blue;	

	pen_16 = (unsigned short *)pen_8;
	pen_32 = (unsigned int *)pen_8;

	switch (g_tDispBuff.iBpp)
	{
		case 8:
		{
			*pen_8 = dwColor;
			break;
		}
		case 16:
		{
			/* 565 */
			red   = (dwColor >> 16) & 0xff;
			green = (dwColor >> 8) & 0xff;
			blue  = (dwColor >> 0) & 0xff;
			dwColor = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
			*pen_16 = dwColor;
			break;
		}
		case 32:
		{
			*pen_32 = dwColor;
			break;
		}
		default:
		{
			printf("can't surport %dbpp\n", g_tDispBuff.iBpp);
			return -1;
			break;
		}
	}

	return 0;
}



// 注册单个DispOpr到设备链表中
void RegisterDispDevice(DispOpr *ptDispOpr){

    ptDispOpr->ptNext = g_DispDevs;
    g_DispDevs = ptDispOpr;

}


/*
	<注册所有显示设备>
	1.调用外部的RegisterFBtoDeviceList
	2.RegisterFBtoDeviceList又会调用RegisterDevice函数
	将声明的g_tFramebufferOpr结构体注册到链表中
*/
int RegisterAllDispDevs(void)
{
    extern void RegisterFBtoDeviceList(void);
    RegisterFBtoDeviceList();

    // extern RegisterWebtoDeviceList(void);
    // RegisterWebtoDeviceList();
    return 0;   
}


// 在设备链表中按照name选择默认设备
int ChooseDefaultDevice(char *name){
	struct DispOpr *DispTmp = g_DispDevs;
    while (DispTmp)
    {
        if (strcmp(name, DispTmp->name) == 0)
        {
            g_DispDefault = DispTmp;
            // printf("int ChooseDefaultDevice(char *name) successed!\n");
            return 0;
        }
        DispTmp = DispTmp->ptNext;
    }
    
    // printf("int ChooseDefaultDevice(char *name) failed!\n");
    return -1;
}

// 初始化默认显示设备
int InitDefaultDevice(void)
{
	int ret;
	
	ret = g_DispDefault->DeviceInit();
	if (ret)
	{
		printf("DeviceInit failed.\n");
		return -1;
	}

	
	ret = g_DispDefault->GetBuffer(&g_tDispBuff);
	if (ret)
	{
		printf("GetBuffer failed.\n");
		return -1;
	}

	line_width  = g_tDispBuff.iXres * g_tDispBuff.iBpp/8;
	pixel_width = g_tDispBuff.iBpp/8;

	return 0;
}



// GetBuffer是对g_tDispBuff结构体中的字段值进行操作，也就是写入数据
// GetDeviceBuffer是获取整个结构体，返回指针
PDispBuff GetDeviceBuffer(void)
{
	return &g_tDispBuff;
}



// 把g_tDispBuff中的数据刷到ptRegion
int FlushDeviceRegion(PRegion ptRegion, PDispBuff ptDispBuff)
{	
	return g_DispDefault->FlushRegion(ptRegion, ptDispBuff);
}